﻿//
// Copyright 2024 Exhunter Technology Co.Ltd2.
//

namespace X18.Framework.Core.Hash
{
    /// <summary>
    /// Crc32算法
    /// </summary>
    public static class Crc32
    {
        private static readonly uint[] table = new uint[256];
        private const uint poly = 0xedb88320;

        static Crc32()
        {
            for (uint i = 0; i < table.Length; i++)
            {
                uint crc = i;
                for (int j = 0; j < 8; j++)
                {
                    crc = (crc & 1) == 1 ? poly ^ (crc >> 1) : (crc >> 1);
                }
                table[i] = crc;
            }
        }

        public static uint ComputeHashToInt32(string data)
        {
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data);
            uint result = ComputeHashToInt32(bytes);
            return result;
        }

        public static uint ComputeHashToInt32(byte[] data)
        {
            uint crc = 0xffffffff;
            for (int i = 0; i < data.Length; i++)
            {
                byte index = (byte)((crc & 0xff) ^ data[i]);
                crc = (crc >> 8) ^ table[index];
            }
            return ~crc;
        }

        public static string ComputeHashToString(string data)
        {
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data);
            byte[] buffer = ComputeHashToBytes(bytes);
            string result = BitConverter.ToString(buffer);
            return result;
        }

        public static string ComputeHashToString(byte[] data)
        {
            byte[] buffer = ComputeHashToBytes(data);
            string result = BitConverter.ToString(buffer);
            return result;
        }

        public static byte[] ComputeHashToBytes(string data)
        {
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data);
            byte[] result = ComputeHashToBytes(bytes);
            return result;
        }

        public static byte[] ComputeHashToBytes(byte[] data)
        {
            uint uhash = ComputeHashToInt32(data);
            byte[] result = new byte[4];
            for (int i = 0; i < 4; i++)
            {
                result[i] = (byte)((uhash >> ((3 - i) * 8)) & 0xff);
            }
            return result;
        }
    }
}
